package com.example.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dto.standard.*;
import com.example.entity.Standard;
import com.example.exception.BizAssertUtils;
import com.example.mapper.StandardMapper;
import com.example.service.StandardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据标准目录表 服务实现类
 * </p>
 *
 * @author zhj
 * @since 2023-03-23
 */
@Service
public class StandardServiceImpl extends ServiceImpl<StandardMapper, Standard> implements StandardService {

    @Autowired
    private StandardMapper standardMapper;

    @Override
    public Page<StandardListDto> getPageList(StandardPageDto standardPageDto) {

        Page<Standard> standardPage = standardMapper.queryStandardPage(standardPageDto);
        Page<StandardListDto> standardListDtoPage = new Page<>(standardPage.getCurrent(),standardPage.getSize(),
                standardPage.getTotal(),standardPage.isSearchCount());

        if(standardPage.getRecords() == null) {
            return standardListDtoPage;
        }

        //返回需要的对象列表
        List<StandardListDto> collect = standardPage.getRecords().stream()
                .map(item -> {
                    return BeanUtil.copyProperties(item, StandardListDto.class);
                })
                .collect(Collectors.toList());

        standardListDtoPage.setRecords(collect);

        return standardListDtoPage;
    }

    @Override
    public StandardDto queryStandardById(Integer id) {
        Standard standard = queryStandardByIdWhitException(id);
        return BeanUtil.copyProperties(standard, StandardDto.class);
    }

    @Override
    public boolean addOrUpdateStandardData(CreateOrUpdateStandardDto createOrUpdateStandardDto) {

        System.out.println(createOrUpdateStandardDto);
        Standard standard = null;
        //判断中文名称是否已经存在
        Standard standardByChinese = standardMapper.selectByChinese(createOrUpdateStandardDto.getStdChinese());
        //判断英文名是否已存在
        Standard standardByEnglish = standardMapper.selectByEnglish(createOrUpdateStandardDto.getStdEnglish());

        if(createOrUpdateStandardDto.getId() == null) {
            //新增
            BizAssertUtils.isNull(standardByChinese, "当前中文名称已存在");
            BizAssertUtils.isNull(standardByEnglish, "当前英文名称已存在");

            standard = new Standard();

            //查询最大账号
            Standard maxIdStand = standardMapper.queryMaxIdStandard();
            int code = 1;
            if(maxIdStand != null) {
                String  maxAccountCode = maxIdStand.getStdCode().replace("BZ", "");
                code = Integer.parseInt(maxAccountCode) + 1;
            }

            //设置账号
            String stdCode = "BZ" + String.format("%05d", code);
            System.out.println(stdCode);
            standard.setStdCode(stdCode);
            //创建时间
            standard.setCreateTime(new Date());
        } else {
            //修改
            //判断中文名称、英文名称是否重复，或是否为原来的
            BizAssertUtils.isTrue(standardByChinese == null || standardByChinese.getId().equals(createOrUpdateStandardDto.getId()),
                    "当前更新的中文名称已存在");
            BizAssertUtils.isTrue(standardByEnglish == null || standardByEnglish.getId().equals(createOrUpdateStandardDto.getId()),
                    "当前更新的英文名称已存在");

            //根据id目录
            standard = queryStandardByIdWhitException(createOrUpdateStandardDto.getId());
            //判断状态：只有在未发布和已停用状态下才能进行更新操作
            BizAssertUtils.isTrue(standard.getStatus() == 1, "当前处于已发布状态，不能进行更新。请停用后在进行操作");
        }

        if(createOrUpdateStandardDto.getStdType().equals("String")) {
            //当数据类型为String时，可以编辑数据长度，而数据精度、取值范围最小值、取值范围最大值、枚举范围（导入时为“引用码表编号”）必须为空；
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdLength() == null, "数据长度不能为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdPrecision() == null ,"数据精度应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdMin().isEmpty(), "取值范围最小值应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdMax().isEmpty(), "取值范围最大值应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getTbId().isEmpty(), "枚举范围应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdDefault().isEmpty(), "默认值应该为空");
        }
        if(createOrUpdateStandardDto.getStdType().equals("Int")) {
            //当数据类型为Int时，可以编辑取值范围最小值及取值范围最大值，而数据长度、数据精度、枚举范围（导入时为“引用码表编号”）必须为空；
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdLength() == null, "数据长度应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdPrecision() == null ,"数据精度应该为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdMin().isEmpty(), "取值范围最小值不能为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdMax().isEmpty(), "取值范围最大值不能为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getTbId().isEmpty(), "枚举范围应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdDefault().isEmpty(), "默认值应该为空");
        }
        if(createOrUpdateStandardDto.getStdType().equals("Float")) {
            //当数据类型为Float时，可以编辑数据精度、取值范围最小值、取值范围最大值，而数据长度、枚举范围（导入时为“引用码表编号”）必须为空；
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdLength() == null, "数据长度应该为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdPrecision() == null ,"数据精度不能为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdMin().isEmpty(), "取值范围最小值不能为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdMax().isEmpty(), "取值范围最大值不能为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getTbId().isEmpty(), "枚举范围应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdDefault().isEmpty(), "默认值应该为空");
        }
        if(createOrUpdateStandardDto.getStdType().equals("Enum")) {
            //当数据类型为Enum时，可以编辑枚举范围（导入时为“引用码表编号”），而数据长度、数据精度、取值范围最小值、取值范围最大值必须为空；
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdLength() == null, "数据长度应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdPrecision() == null ,"数据精度应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdMin().isEmpty(), "取值范围最小值应该为空");
            BizAssertUtils.isTrue(createOrUpdateStandardDto.getStdMax().isEmpty(), "取值范围最大应该为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getTbId().isEmpty(), "枚举范围不能为空");
            BizAssertUtils.isFalse(createOrUpdateStandardDto.getStdDefault().isEmpty(), "默认值不能为空");
        }

        standard.setStdChinese(createOrUpdateStandardDto.getStdChinese());
        standard.setStdEnglish(createOrUpdateStandardDto.getStdEnglish());
        standard.setStdDesc(createOrUpdateStandardDto.getStdDesc());
        standard.setStdSource(createOrUpdateStandardDto.getStdSource());
        standard.setStdType(createOrUpdateStandardDto.getStdType());
        standard.setStdLength(createOrUpdateStandardDto.getStdLength());
        standard.setStdPrecision(createOrUpdateStandardDto.getStdPrecision());
        standard.setStdDefault(createOrUpdateStandardDto.getStdDefault());
        standard.setStdMin(createOrUpdateStandardDto.getStdMin());
        standard.setStdMax(createOrUpdateStandardDto.getStdMax());
        standard.setTbId(createOrUpdateStandardDto.getTbId());
        standard.setUpdateTime(new Date());
        standard.setStdEmpty(createOrUpdateStandardDto.getStdEmpty());

        return this.saveOrUpdate(standard);
    }

    @Override
    public Boolean updateStandardStatus(UpdateStandardStatusDto updateStandardStatusDto) {
        Standard standard = queryStandardByIdWhitException(updateStandardStatusDto.getId());

        //判断是否需要修改
        BizAssertUtils.isFalse(standard.getStatus().equals(updateStandardStatusDto.getStatus()), "状态未变更，不更新!");
        BizAssertUtils.isFalse(updateStandardStatusDto.getStatus() == 0, "状态不能变更为未发布!");
        BizAssertUtils.isFalse(standard.getStatus() == 0 && updateStandardStatusDto.getStatus() == 2, "状态不能由未发布变更为已停用");
        standard.setStatus(updateStandardStatusDto.getStatus());

        //更新
        return this.updateById(standard);
    }

    @Override
    public Boolean delStandard(Integer id) {
        Standard standard = queryStandardByIdWhitException(id);

        //判断是否能进行删除操作
        BizAssertUtils.isTrue(standard.getStatus().equals(0), "当前状态下不能进行删除操作");

        standardMapper.deleteById(standard.getId());
        return true;
    }

    //通过id查找标准目录，不存在则抛出异常
    private Standard queryStandardByIdWhitException(Integer id) {
        Standard standard = standardMapper.selectById(id);
        BizAssertUtils.notNull(standard, "目录不存在");
        return standard;
    }
}
